package com.xbongbong.saas.analytical.impl;

import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.xbongbong.paas.constant.MessageConstant;
import com.xbongbong.paas.constant.PaasConstant;
import com.xbongbong.paas.enums.StageTypeEnum;
import com.xbongbong.paas.help.FormExplainHelp;
import com.xbongbong.paas.help.team.TeamUserHelp;
import com.xbongbong.paas.pojo.dto.ValidateDataDTO;
import com.xbongbong.paas.toolbox.exception.XbbException;
import com.xbongbong.paas.toolbox.util.Arith;
import com.xbongbong.paas.toolbox.util.StringUtil;
import com.xbongbong.pro.constant.AttrLenthConstant;
import com.xbongbong.pro.enums.errorcodes.OpportunityErrorCodeEnum;
import com.xbongbong.pro.enums.errorcodes.SystemErrorCodeEnum;
import com.xbongbong.pro.formdata.pojo.SaasNeedRedundantAttrPojo;
import com.xbongbong.saas.analytical.SaasValidateAnalyticalService;
import com.xbongbong.saas.constant.BasicConstant;
import com.xbongbong.saas.domain.entity.SaleStageEntity;
import com.xbongbong.saas.domain.entity.ext.OpportunityEntityExt;
import com.xbongbong.saas.enums.SelectProductEnum;
import com.xbongbong.saas.enums.XbbRefTypeEnum;
import com.xbongbong.saas.enums.business.ContractEnum;
import com.xbongbong.saas.enums.business.CustomerManagementEnum;
import com.xbongbong.saas.enums.business.SalesOpportunityEnum;
import com.xbongbong.saas.help.AnalyticalHelp;
import com.xbongbong.saas.help.SaasDataInitHelp;
import com.xbongbong.saas.help.SaasProductHelp;
import com.xbongbong.saas.help.SaveFormatHelp;
import com.xbongbong.saas.model.OpportunityModel;
import com.xbongbong.saas.model.SaleStageModel;
import com.xbongbong.saas.toolbox.help.FastJsonHelper;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Set;

import static com.xbongbong.saas.toolbox.help.FastJsonHelper.getDoubleOrDefaultFromFormData;
import static com.xbongbong.saas.toolbox.help.FastJsonHelper.getStringOrDefaultFromFormData;

/**
 * @author 吴峰
 * @date 2021/07/15 17:15
 */
@Service("opportunityAnalyticalServiceImpl")
public class OpportunityValidateAnalyticalServiceImpl implements SaasValidateAnalyticalService {
    @Resource
    private FormExplainHelp formExplainHelp;
    @Resource
    private SaleStageModel saleStageModel;
    @Resource
    private OpportunityModel opportunityModel;
    @Resource
    private SaasProductHelp saasProductHelp;
    @Resource
    private AnalyticalHelp analyticalHelp;
    @Resource
    private TeamUserHelp teamUserHelp;

    @Override
    public List<Integer> type() {
        return Arrays.asList(XbbRefTypeEnum.SALES_OPPORTUNITY.getCode());
    }

    @Override
    public void analyticalData(ValidateDataDTO validateDataDTO) throws XbbException {
        beforeSave(validateDataDTO);
        teamUserHelp.beforeVerifyUserTeam(validateDataDTO);
    }
    
    public void beforeSave(ValidateDataDTO validateDataDTO) throws XbbException {
        String corpid = validateDataDTO.getCorpid();
        JSONObject data = validateDataDTO.getData();
        Long id = validateDataDTO.getDataId();
        SaveFormatHelp.formatLinkBusiness4Save(data, SalesOpportunityEnum.CUSTOMER_NAME.getAttr(), SalesOpportunityEnum.CUSTOMER_NAME_LINK_TEXT.getAttr(), SalesOpportunityEnum.CUSTOMER_NAME.getFieldType());
        SaveFormatHelp.formatLinkBusiness4Save(data, SalesOpportunityEnum.CONTACT_NAME.getAttr(), SalesOpportunityEnum.CONTACT_NAME_LINK_TEXT.getAttr(), SalesOpportunityEnum.CONTACT_NAME.getFieldType());
        SaveFormatHelp.formatLinkBusiness4Save(data, SalesOpportunityEnum.DECISION_MAKER.getAttr(), SalesOpportunityEnum.DECISION_MAKER_ID_LINK_TEXT.getAttr(), SalesOpportunityEnum.DECISION_MAKER.getFieldType());
        SaveFormatHelp.formatLinkBusiness4Save(data, SalesOpportunityEnum.LINK_COMPETITOR.getAttr(), SalesOpportunityEnum.LINK_COMPETITOR_LINK_TEXT.getAttr(),SalesOpportunityEnum.LINK_COMPETITOR.getFieldType());
        SaveFormatHelp.formatLinkBusiness4Save(data, SalesOpportunityEnum.WIN_COMPETITOR.getAttr(), SalesOpportunityEnum.WIN_COMPETITOR_LINK_TEXT.getAttr(),SalesOpportunityEnum.WIN_COMPETITOR.getFieldType());

        boolean isNew = analyticalHelp.isNew(id, validateDataDTO.getTaskId(), corpid);
        // id不为空代表编辑
        if (isNew) {
            // 是否归档，1归档，2未归档
            data.put(SalesOpportunityEnum.IS_ARCHIVED.getAttr(), BasicConstant.TWO);
            //销售阶段
            String salesStageCode = getStringOrDefaultFromFormData(data, SalesOpportunityEnum.SALE_STAGE.getAttr(), "");
            if(StringUtil.isNotEmpty(salesStageCode)){
                Long formId = validateDataDTO.getFormId();
                SaleStageEntity stageEntity = saleStageModel.getByCode(corpid, formId, salesStageCode);
                //销售阶段为空
                if(stageEntity == null){
                    throw new XbbException(SystemErrorCodeEnum.API_ERROR_100404);
                }
                Integer stageType = stageEntity.getType();
                //输单，取消 归档
                if(stageType != null && (stageType.equals(StageTypeEnum.FAIL_STAGE.getType()) || stageType.equals(StageTypeEnum.CANCEL_STAGE.getType()))){
                    data.put(SalesOpportunityEnum.IS_ARCHIVED.getAttr(), BasicConstant.ONE);
                }
            }
        } else {
            if (Objects.equals(validateDataDTO.getIsImport(), 1)) {
                // 销售阶段不允许编辑
                OpportunityEntityExt opportunityEntityExt = opportunityModel.getByKey(id, corpid);
                if (Objects.isNull(opportunityEntityExt)) {
                    throw new XbbException(SystemErrorCodeEnum.API_ERROR_100001, MessageConstant.FORM_DATA_NOT_EXIST);
                }
                String oldLossReason = FastJsonHelper.getStringFromFormData(opportunityEntityExt.getData(), SalesOpportunityEnum.WASTAGE.getAttr());
                String oldStageCode = FastJsonHelper.getStringFromFormData(opportunityEntityExt.getData(), SalesOpportunityEnum.SALE_STAGE.getAttr());
                if (oldLossReason != null) {
                    data.put(SalesOpportunityEnum.WASTAGE.getAttr(), oldLossReason);
                }
                if (oldStageCode != null) {
                    data.put(SalesOpportunityEnum.SALE_STAGE.getAttr(), oldStageCode);
                }
            }
        }

        Boolean productCanSee = true;

        if (!isNew){
            productCanSee = formExplainHelp.attrCanSee(validateDataDTO.getExplainMap().get(SalesOpportunityEnum.PRODUCTS.getAttr()),id,validateDataDTO.getCreatorId(),validateDataDTO.getLoginUser(),corpid,XbbRefTypeEnum.SALES_OPPORTUNITY.getCode());
        }
        if (isNew || productCanSee){
            JSONArray productArr = FastJsonHelper.getJsonArrOrDefaultFromFormData(data, SalesOpportunityEnum.PRODUCTS.getAttr(), new JSONArray());
            validateProductDemo(productArr,corpid);
            // 计算成本毛利等数据
            calculateOpportunityCost(validateDataDTO);
        }


        for (Map.Entry<String,Object> entry : SaasDataInitHelp.initOpportunity().entrySet()){
            SaasDataInitHelp.antDataSet(data,entry.getKey(),entry.getValue());
        }
        validateDataDTO.setData(data);
        Map<String,Boolean> attrCanSeeMap = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
        attrCanSeeMap.put(SalesOpportunityEnum.PRODUCTS.getAttr(),productCanSee);
        SaasNeedRedundantAttrPojo saasNeedRedundantAttrPojo = new SaasNeedRedundantAttrPojo();
        saasNeedRedundantAttrPojo.setAttrCanSeeMap(attrCanSeeMap);
        validateDataDTO.setSaasNeedRedundantAttrPoJo(saasNeedRedundantAttrPojo);
    }

    /**
     * 机会产品校验
     * @param productList
     * @param corpid
     * @throws XbbException
     */
    private void validateProductDemo(JSONArray productList, String corpid) throws XbbException {
        Set<Long> pageProductIds = new HashSet<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
        if (Objects.isNull(productList) || productList.isEmpty()){
            return;
        }
        for (Object obj : productList){
            JSONObject json = JSONObject.parseObject(obj.toString());
            Long productId = json.getLong(SelectProductEnum.PRODUCT.getAttr());
            pageProductIds.add(productId);
        }
        saasProductHelp.productExitContract(productList,corpid,new ArrayList<>(pageProductIds));
    }

    /**
     * 计算机会成本
     *
     * @param validateDataDTO 数据
     * @throws XbbException
     * @author long.rao
     * @date 2019-03-04 14:11
     */
    private void calculateOpportunityCost(ValidateDataDTO validateDataDTO) throws XbbException{
        JSONObject dataList = validateDataDTO.getData();
//        JSONObject product = saasUpdateHelp.getJsonObjectOrDefaultFromFormData(dataList, SalesOpportunityEnum.PRODUCTS.getAttr(), new JSONObject());
//        JSONArray productArr = product.getJSONArray(StringConstant.PRODUCT_LIST);
        JSONArray productArr = FastJsonHelper.getJsonArrOrDefaultFromFormData(dataList, SalesOpportunityEnum.PRODUCTS.getAttr(), new JSONArray());
        productArr = productArr == null ? new JSONArray() : productArr;

        double estimateCost = 0D;
        for (int i = 0; i < productArr.size(); i++) {
            JSONObject productObj = productArr.getJSONObject(i);
            double productNum = StringUtil.toDouble(productObj.getString(SelectProductEnum.NUM.getAttr()), 0D);
//            if (!productObj.containsKey("estimateCost")) {
//                productObj.put("estimateCost", productObj.getString(ProductEnum.COST.getSaasAttr()));
//            }
            double productCost = StringUtil.toDouble(productObj.getString(ContractEnum.ESTIMATE_COST.getSaasAttr()), 0D);
            estimateCost = Arith.add(estimateCost, Arith.mul(productNum, productCost));
        }
        Double estimateAmount = getDoubleOrDefaultFromFormData(dataList, SalesOpportunityEnum.ESTIMATE_AMOUNT.getAttr(), 0D);
        //毛利
        double grossProfit = Arith.sub(estimateAmount, estimateCost);
        dataList.put(SalesOpportunityEnum.COST.getAttr(), Arith.round(estimateCost, 2));
        dataList.put(SalesOpportunityEnum.GROSS_PROFIT.getAttr(), Arith.round(grossProfit, 2));
        //毛利率
        if (Double.compare(estimateAmount, BasicConstant.ZERO_DOUBLE) != 0) {
            dataList.put(SalesOpportunityEnum.GROSS_PROFIT_RATE.getAttr(), Arith.round(Arith.div(grossProfit, estimateAmount), 4));
        }
    }
}
